const fs = require('fs');
const path = require('path');
const MFS = require('memory-fs');
const webpack = require('webpack');
const chokidar = require('chokidar');
const OpenBrowserPlugin = require('open-browser-webpack-plugin');
const clientConfig = require('../build/config')({client: true});
const serverConfig = require('../build/config')({server: true});

const readFile = (fs, file) => {
    try{
        return fs.readFileSync(path.join(clientConfig.output.path, file), 'utf-8');
    } catch (e) {}
}

module.exports = (app, port, templatePath, cb) => {

    let bundle, template, clientManifest, ready;
    const readyPromise = new Promise(r => {
        ready = r;
    });
    const update = () => {
        ready();
        cb(bundle, {template, clientManifest});
    };

    template = fs.readFileSync(templatePath, 'utf-8');
    chokidar.watch(templatePath).on('change', () => {
        template = fs.readFileSync(templatePath, 'utf-8');
        console.log('index.html template updated.');
        update();
    });

    clientConfig.entry = ['webpack-hot-middleware/client', clientConfig.entry];
    clientConfig.plugins.push(
        new webpack.HotModuleReplacementPlugin(),
        new OpenBrowserPlugin({
            url: `http://localhost:${port}`
        })
    );

    const clientCompiler = webpack(clientConfig);
    const devMiddleware = require('webpack-dev-middleware')(clientCompiler, {
        publicPath: clientConfig.output.publicPath,
        noInfo: true,
        quiet: true,
        hot: true,
        stats: {colors: true}
    });
    app.use(devMiddleware);
    clientCompiler.plugin('done', stats => {
        stats = stats.toJson();
        stats.errors.forEach(err => {
            console.log(err);
        });
        stats.warnings.forEach(err => {
            console.log(err);
        });
        if(stats.errors.length){
            return;
        }
        clientManifest = JSON.parse(readFile(
            devMiddleware.fileSystem,
            'vue-ssr-client-manifest.json'
        ));
        update();
    });

    app.use(require('webpack-hot-middleware')(clientCompiler));

    const serverCompiler = webpack(serverConfig);
    const mfs = new MFS();
    serverCompiler.outputFileSystem = mfs;
    serverCompiler.watch({}, (err, stats) => {
        if(err) throw err;
        stats = stats.toJson();
        if (stats.errors.length){
            return;
        }
        bundle = JSON.parse(readFile(mfs, 'vue-ssr-server-bundle.json'));
        update();
    });

    return readyPromise;
}